Adam

使用 Adam 算法更新参数权重。支持 Nesterov 动量。

算法逻辑如下:

\[\begin{split}m_t = m_{t-1} + (g_t - m_{t-1}) \cdot (1 - \beta_1) \\ v_t = v_{t-1} + (g_t^2 - v_{t-1}) \cdot (1 - \beta_2) \\ \hat{lr} = lr \cdot \frac{\sqrt{1 - \beta_2^t}}{1 - \beta_1^t}\end{split}\]

如果不启用 Nesterov:

\[w_t = w_{t-1} - \hat{lr} \cdot \frac{m_t}{\sqrt{v_t} + \epsilon}\]

如果启用 Nesterov:

\[w_t = w_{t-1} - \hat{lr} \cdot \frac{m_t \cdot \beta_1 + (1 - \beta_1) \cdot g_t}{\sqrt{v_t} + \epsilon}\]
输入:
  • m - 一阶矩向量地址(输入/输出)。

  • v - 二阶矩向量地址(输入/输出)。

  • gradient - 梯度向量地址。

  • weight - 权重向量地址(输入/输出)。

  • beta1 - 一阶矩估计的指数衰减率。

  • beta2 - 二阶矩估计的指数衰减率。

  • beta1_power - \(\beta_1^t\) 的值(指针形式传入)。

  • beta2_power - \(\beta_2^t\) 的值(指针形式传入)。

  • eps - 数值稳定性项 epsilon。

  • learning_rate - 学习率。

  • nesterov - 是否启用 Nesterov 动量(0: 不启用, 1: 启用)。

  • start - 计算的起始索引(包含)。

  • end - 计算的结束索引(不包含)。

  • core_mask - 核掩码(仅适用于共享存储版本)。

输出:
  • m - 更新后的一阶矩。

  • v - 更新后的二阶矩。

  • weight - 更新后的权重。

支持平台:

FT78NE MT7004

备注

  • 仅支持 fp32 数据类型。

共享存储版本:

void fp_adam_s(float *m, float *v, const float *gradient, float *weight, float beta1, float beta2, float *beta1_power, float *beta2_power, float eps, float learning_rate, int nesterov, int start, int end, int core_mask)

C调用示例:

 1#include <stdio.h>
 2
 3int main(int argc, char* argv[]) {
 4    // 假设所有数据均位于DDR空间
 5    float* m = (float*)0xC0000000;
 6    float* v = (float*)0xC1000000;
 7    float* gradient = (float*)0xC2000000;
 8    float* weight = (float*)0xC3000000;
 9
10    // 标量参数
11    float beta1 = 0.9f;
12    float beta2 = 0.999f;
13    float beta1_power_val = 0.9f;   // beta1^1
14    float beta2_power_val = 0.999f; // beta2^1
15    float* beta1_power = &beta1_power_val;
16    float* beta2_power = &beta2_power_val;
17    float eps = 1e-8f;
18    float learning_rate = 0.001f;
19    int nesterov = 1;
20
21    int start = 0;
22    int end = 800000; // 元素总数
23    int core_mask = 0xff; // 使用所有核心
24
25    fp_adam_s(m, v, gradient, weight, beta1, beta2, beta1_power, beta2_power,
26              eps, learning_rate, nesterov, start, end, core_mask);
27
28    return 0;
29}

私有存储版本:

void fp_adam_p(float *m, float *v, const float *gradient, float *weight, float beta1, float beta2, float *beta1_power, float *beta2_power, float eps, float learning_rate, int nesterov, int start, int end)

C调用示例:

 1#include <stdio.h>
 2
 3int main(int argc, char* argv[]) {
 4    // 假设所有数据均位于L2/AM空间
 5    float* m = (float*)0x10820000;
 6    float* v = (float*)0x10830000;
 7    float* gradient = (float*)0x10840000;
 8    float* weight = (float*)0x10850000;
 9
10    float beta1 = 0.9f;
11    float beta2 = 0.999f;
12    float beta1_power_val = 0.9f;
13    float beta2_power_val = 0.999f;
14    float eps = 1e-8f;
15    float learning_rate = 0.001f;
16    int nesterov = 0;
17    int start = 0;
18    int end = 2000;
19
20    fp_adam_p(m, v, gradient, weight, beta1, beta2, &beta1_power_val, &beta2_power_val,
21              eps, learning_rate, nesterov, start, end);
22
23    return 0;
24}